package awesomeTask

import (
	awesomeTask "awesomeTask/config"
	"awesomeTask/system/helper"
	"awesomeTask/system/log"
	"bytes"
	"fmt"
	"net"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

//&content-length:187&chunk:0&index:1&
var HeaderSplit string = "--#&content-length:{}&chunk:{}&index:{}&#--"              //固定的头部数据
var HeaderSplitRegx string = "--#&content-length:(.*?)&chunk:(.*?)&index:(.*?)&#--" //固定的头部数据
//var ConnectionMap map[string]map[string][]byte = make(map[string]map[string][]byte)
var BufferMap map[string]map[string]int = make(map[string]map[string]int)
var SafeBufferMap sync.Map
var SafeConnectionMap sync.Map

/**
解决tcp粘包
*/
func ReadBytes(conn net.Conn) ([]byte, error) {
	mapInfo, ok := SafeConnectionMap.Load(conn.RemoteAddr())
	if ok == false {
		mapInfo = make(map[string]map[string][]byte)
		SafeConnectionMap.Store(conn.RemoteAddr().String(), mapInfo)
	}
	ConnectionMap := mapInfo.(map[string]map[string][]byte)
	//bufferSize:=0
	bufferArray := make([][]byte, 1)
	for true {
		if ConnectionMap[conn.RemoteAddr().String()] != nil && ConnectionMap[conn.RemoteAddr().String()]["unFinishBuffer"] != nil {
			buffer := make([]byte, 512)
			n, err := conn.Read(buffer)
			if err != nil {
				return []byte(""), err
			}
			if BufferMap[conn.RemoteAddr().String()]["unFinishBufferLength"] <= n {
				//fmt.Println(BufferMap[conn.RemoteAddr().String()]["unFinishBufferLength"],"bytes===>")
				unFinishLength := BufferMap[conn.RemoteAddr().String()]["unFinishBufferLength"]
				res := BytesCombine(ConnectionMap[conn.RemoteAddr().String()]["unFinishBuffer"], buffer[0:unFinishLength])
				delete(ConnectionMap[conn.RemoteAddr().String()], "unFinishBuffer")
				delete(BufferMap, conn.RemoteAddr().String())
				ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = buffer[unFinishLength:len(buffer)]
				return res, nil
			} else {
				BufferMap[conn.RemoteAddr().String()]["unFinishBufferLength"] -= n
				ConnectionMap[conn.RemoteAddr().String()]["unFinishBuffer"] = BytesCombine(ConnectionMap[conn.RemoteAddr().String()]["unFinishBuffer"], buffer[0:n])
				continue
			}
		}
		if ConnectionMap[conn.RemoteAddr().String()] != nil && ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] != nil {
			packetInfo := Unpacket(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"])
			if packetInfo["isFinished"] != nil && packetInfo["isFinished"].(bool) {
				ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = nil
				if len(packetInfo["resBuffer"].([]byte)) != 0 {
					if ConnectionMap[conn.RemoteAddr().String()] == nil {
						ConnectionMap[conn.RemoteAddr().String()] = make(map[string][]byte)
					}
					if ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] == nil {
						ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = packetInfo["resBuffer"].([]byte)
					} else {
						ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = BytesCombine(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"], packetInfo["resBuffer"].([]byte))
					}
					//fmt.Println(string(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"]))
				}
				return packetInfo["buffer"].([]byte), nil
			}
		}
		buffer := make([]byte, 512)
		_, err := conn.Read(buffer)
		if err != nil {
			return []byte(""), err
		}
		if ConnectionMap[conn.RemoteAddr().String()] != nil && ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] != nil {
			buffer = BytesCombine(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"], buffer)
			ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = nil
		}
		packetInfo := Unpacket(buffer)
		if packetInfo["isFinished"] == nil {
			continue
		}
		if packetInfo["isFinished"] != nil && packetInfo["isFinished"].(bool) {
			if len(packetInfo["resBuffer"].([]byte)) != 0 {
				if ConnectionMap[conn.RemoteAddr().String()] == nil {
					ConnectionMap[conn.RemoteAddr().String()] = make(map[string][]byte)
				}
				if ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] == nil {
					ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = packetInfo["resBuffer"].([]byte)
				} else {
					ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = BytesCombine(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"], packetInfo["resBuffer"].([]byte))
				}
				//fmt.Println(string(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"]))
			}
			return packetInfo["buffer"].([]byte), nil
		}
		if ConnectionMap[conn.RemoteAddr().String()] == nil {
			ConnectionMap[conn.RemoteAddr().String()] = make(map[string][]byte)
		}
		if ConnectionMap[conn.RemoteAddr().String()]["unFinishBuffer"] == nil && packetInfo["buffer"] != nil {
			ConnectionMap[conn.RemoteAddr().String()]["unFinishBuffer"] = packetInfo["buffer"].([]byte)
			if BufferMap[conn.RemoteAddr().String()] == nil {
				BufferMap[conn.RemoteAddr().String()] = make(map[string]int)
			}
			BufferMap[conn.RemoteAddr().String()]["unFinishBufferLength"] = packetInfo["unFinishBufferLength"].(int)
		}
		ConnectionMap[conn.RemoteAddr().String()]["resBuffer"] = BytesCombine(ConnectionMap[conn.RemoteAddr().String()]["resBuffer"], packetInfo["resBuffer"].([]byte))
	}
	return BytesCombine(bufferArray...), nil

}

//线程安全的读取tcp的数据  同时避免tcp 粘包
func ReadTcpStreamSafe(conn net.Conn) ([]byte, error) {
	uniqueId := conn.RemoteAddr().String()
	if _, ok := SafeBufferMap.Load(uniqueId); !ok {
		SafeBufferMap.Store(uniqueId, []byte(""))
	}
	for true {
		lastRemainBuffer, _ := SafeBufferMap.Load(uniqueId)
		resultBuffer, remainBuffer, err := UnpacketSafe(lastRemainBuffer.([]byte))
		if err != nil {
			if _, ok := SafeBufferMap.Load(uniqueId); !ok {
				SafeBufferMap.Delete(uniqueId)
			}
			return []byte(""), err
		}
		SafeBufferMap.Store(uniqueId, remainBuffer)
		if len(resultBuffer) > 0 {
			return resultBuffer, nil
		}
		buffer := make([]byte, 512)
		n, err := conn.Read(buffer)
		//fmt.Println(buffer,"buffer")
		buffer = buffer[0:n]
		if err != nil {
			//fmt.Println(buffer,"buffer===>||")
			SafeBufferMap.Delete(uniqueId)
			return []byte(""), err
		}

		resultBuffer, remainBuffer, err = UnpacketSafe(BytesCombine(lastRemainBuffer.([]byte), buffer))
		if err != nil {
			//fmt.Println(buffer,"buffer===>|")
			//fmt.Println(lastRemainBuffer,"remainBuffer===>|")
			if _, ok := SafeBufferMap.Load(uniqueId); !ok {
				SafeBufferMap.Delete(uniqueId)
			}
			return []byte(""), err
		}
		SafeBufferMap.Store(uniqueId, remainBuffer)
		if len(resultBuffer) > 0 {
			return resultBuffer, nil
		} else {
			//fmt.Println(buffer,"buffer===>")
			//fmt.Println(string(remainBuffer),"remainBuffer===>")
		}
	}
	return []byte(""), nil
}
func BytesCombine(pBytes ...[]byte) []byte {
	length := len(pBytes)
	s := make([][]byte, length)
	for index := 0; index < length; index++ {
		s[index] = pBytes[index]
	}
	sep := []byte("")
	return bytes.Join(s, sep)
}
func ReadString(conn net.Conn) (string, error) {
	data, err := ReadTcpStreamSafe(conn)
	if strings.Index(string(data), "load==>load") != -1 {
		fmt.Println(string(data), "错误的包信息")
		//readData :=make([]byte,1024)
		//conn.Read(readData)
		//fmt.Println(readData,"readData")
	}
	return string(data), err
}
func SafeCheck(message string) bool {
	defer func() bool {
		if r := recover(); r != nil {
			return false
		}
		return false
	}()
	data := helper.JsonDecode(message).(map[string]interface{})
	if data["clientToken"].(string) != awesomeTask.GetConfigByKey("clientToken") {
		return false
	}
	return true
}

/**
此段代码用于解决tcp粘包的问题
*/
func PacketData(data []byte) []byte {
	/**
	chunk 用于后续分片 chunk
	index 第几片
	*/
	header := helper.Format("--#&content-length:{}&chunk:{}&index:{}&#--", strconv.Itoa(len(string(data))), strconv.Itoa(0), strconv.Itoa(1))

	headerBuffer := []byte(header)
	return BytesCombine(headerBuffer, data)
}

/**
第一个返回参数表示一个完整的tcp数据包
第二个返回参数表余下的数据包
第三个参数表示粗破
*/
func UnpacketSafe(data []byte) ([]byte, []byte, error) {
	dataString := string(data)
	r, err := regexp.Compile(HeaderSplitRegx)
	if err != nil {
		log.GetLogger().Error("tcp err" + err.Error())
		return []byte(""), []byte(""), err
	}
	match := r.FindStringSubmatch(dataString)
	index := r.FindStringIndex(dataString)
	if len(match) >= 4 {
		dataStringLength := len(dataString)
		contentLength := parseInt(match[1])
		contentStartIndex := index[0] + len([]byte(match[0]))
		if (contentLength + contentStartIndex) > len(dataString) {
			//表示由于传输的数据过大被tcp进行分片传输 等待下一片传输的数据
			return []byte(""), []byte(dataString), nil
		} else {
			return []byte(dataString[contentStartIndex : contentStartIndex+contentLength]),
				[]byte(dataString[contentStartIndex+contentLength : dataStringLength]),
				nil
		}
	} else {
		//此处可能表示本次数据里面没有找到一个有效的头部信息 可能传输方未能按照拟定的协进行传输
		return []byte(""), []byte(dataString), nil
	}
}

/**
解析自定义的tcp数据
*/
func Unpacket(data []byte) map[string]interface{} {
	dataString := string(data)
	r, err := regexp.Compile(HeaderSplitRegx)
	if err != nil {
		panic(err)
	}
	match := r.FindStringSubmatch(dataString)
	index := r.FindStringIndex(dataString)
	if len(match) >= 4 {
		contentLength := parseInt(match[1])
		info := make(map[string]interface{})
		info["start"] = index[0] + len([]byte(match[0]))
		info["content-length"] = contentLength
		start_at := info["start"].(int)
		end_at := info["content-length"].(int) + start_at
		if end_at > len(data) {
			end_at = len(data)
		}
		content := data[start_at:end_at]
		info["buffer"] = content
		info["resBuffer"] = data[end_at:len(data)]
		info["isFinished"] = len(content) >= contentLength
		info["unFinishBufferLength"] = contentLength - len(content)
		info["res"] = data[end_at:len(data)]
		return info
	}
	return make(map[string]interface{})
}
func parseInt(string2 string) int {
	num, err := strconv.Atoi(string2)
	if err != nil {
		panic(err.Error())
	}
	return num
}
